package com.zh.auth.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.auth.domain.dto.AddPermission2RoleDto;
import com.zh.auth.domain.dto.DelPermission2RoleDto;
import com.zh.auth.mapper.RolePermissionMapper;
import com.zh.auth.properties.RedisKeyProperties;
import com.zh.auth.service.PermissionService;
import com.zh.auth.service.RolePermissionService;

import com.zh.common.exception.BusinessException;
import com.zh.common.utils.RedisUtil;
import com.zh.web.domain.auth.entity.Permission;
import com.zh.web.domain.auth.entity.RolePermission;
import com.zh.web.enums.ProtectedPermission;
import com.zh.web.enums.ProtectedRole;
import com.zh.web.enums.Status;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@Slf4j
public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper, RolePermission> implements RolePermissionService {
    private final PermissionService permissionService;
    private final RolePermissionMapper rolePermissionMapper;
    private final RedisKeyProperties redisKeyProperties;
    private final RedisUtil redisUtil;

    @Transactional
    public String addPermission2Role(AddPermission2RoleDto addPermission2RoleDto) {
        Integer permissionCode = addPermission2RoleDto.getPermissionCode();
        Permission permission = Optional.of(permissionService.getByCode(permissionCode))
                .orElseThrow(() -> new BusinessException("权限不存在"));
        if (Status.DISABLE.equals(permission.getStatus())) {
            throw new BusinessException("权限已关闭");
        }
        RolePermissionService proxy = (RolePermissionService) AopContext.currentProxy();
        RolePermission rolePermission = BeanUtil.copyProperties(addPermission2RoleDto, RolePermission.class);
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleCode, rolePermission.getRoleCode());
        wrapper.eq(RolePermission::getPermissionCode, rolePermission.getPermissionCode());
        if (rolePermissionMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("该角色已添加该权限!");
        }
        proxy.removeIfMarkedAsDeleted(List.of(addPermission2RoleDto.getRoleCode()));
        redisUtil.delete(redisKeyProperties.getRolePermissionList());
        boolean success = rolePermissionMapper.insert(rolePermission) > 0;
        if (success) {
            return "添加成功";
        } else {
            throw new BusinessException("添加失败");
        }
    }

    @Override
    public List<RolePermission> listRolePermission() {
        List<RolePermission> rolePermissionList = redisUtil.getList(redisKeyProperties.getRolePermissionList(), RolePermission.class);
        if (CollUtil.isNotEmpty(rolePermissionList)) {
            return rolePermissionList;
        }
        rolePermissionList = rolePermissionMapper.selectList(null);
        redisUtil.setList(redisKeyProperties.getRolePermissionList(), rolePermissionList);
        return rolePermissionList;
    }

    @Override
    public String delPermission2Role(DelPermission2RoleDto delPermission2RoleDto) {
        if (delPermission2RoleDto.getRoleCode().equals(ProtectedRole.ADMIN.getRoleCode())
                && delPermission2RoleDto.getPermissionCode().equals(ProtectedPermission.ALL.getPermissionCode())) {
            throw new BusinessException("管理员该权限不允许删除");
        }
        LambdaUpdateWrapper<RolePermission> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(RolePermission::getRoleCode, delPermission2RoleDto.getRoleCode());
        wrapper.eq(RolePermission::getPermissionCode, delPermission2RoleDto.getPermissionCode());
        redisUtil.delete(redisKeyProperties.getRolePermissionList());
        boolean success = rolePermissionMapper.delete(wrapper) > 0;
        if (success) {
            return "删除成功";
        } else {
            throw new BusinessException("删除失败");
        }
    }

    @Override
    public List<RolePermission> selectPermissionByRole(Integer roleCode) {
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleCode, roleCode);
        return rolePermissionMapper.selectList(wrapper);
    }

    @Override
    public void removeIfMarkedAsDeleted(List<Integer> roleCode) {
        rolePermissionMapper.permanentlyDeleteByIds(roleCode);
    }
}
